package com.spring.interceptor;

import java.io.IOException;
import java.io.PrintWriter;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.alibaba.fastjson.JSON;
import com.spring.util.CommonResult;
import com.spring.util.ConstantsStatus;

public class AppInterceptor implements HandlerInterceptor {
	private static Logger LOGGER = Logger.getLogger(AppInterceptor.class);
	private static Map<String,String> signMap=null;
	static{
		signMap=new HashMap<>();
		signMap.put("60c3fa21e92f4f52b30836bad42f8e0a", "ecd8d0c738cb6487cea6669f061048a8");
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		CommonResult<Object> commonResult = new CommonResult<Object>();
		LOGGER.debug("Request From:" + request.getRemoteHost() + "====>" + request.getRequestURL());
		Map<String, String[]> paramMap = request.getParameterMap();
		String[] sign = paramMap.get("signature");
		String[] appId = paramMap.get("appId");
		String[] signtime = paramMap.get("signtime");

		if (ArrayUtils.isEmpty(sign) || ArrayUtils.isEmpty(appId) || ArrayUtils.isEmpty(signtime)
				|| signtime[0].length() != 10 || StringUtils.isBlank(signMap.get(appId[0]))) {
			commonResult.setResult(ConstantsStatus.SC5001, "无效验签参数", false);
			println(response, commonResult);
			return false;
		}
		long requestTime = 0;
		try {
			String join = toStr(signtime);
			requestTime = Long.parseLong(join);
		} catch (NumberFormatException e) {
			commonResult.setResult(ConstantsStatus.SC5001, "非法参数", false);
			println(response, commonResult);
			return false;
		}

		if (System.currentTimeMillis() - requestTime * 1000 > 60 * 1000) {
			commonResult.setResult(ConstantsStatus.SC5001, "请求已过期", false);
			println(response, commonResult);
			return false;
		}
		String serverSign = getSign(signMap.get(appId[0]), paramMap);
		LOGGER.debug("加密后：" + serverSign);
		if (toStr(sign).equals(serverSign)) {
			LOGGER.debug("恭喜,认证通过啦.");
			return true;
		}
		LOGGER.debug("Sorry,认证失败.");
		commonResult.setResult(ConstantsStatus.SC4000, "验签失败", false);
		println(response, commonResult);
		return false;
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
		// TODO Auto-generated method stub
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
		// TODO Auto-generated method stub

	}

	/**
	 * 获取签名值
	 * 
	 * @param secretKey
	 * @param params
	 *            请求参数
	 * @return
	 */
	private static String getSign(String secretKey, Map<String, String[]> params) {

		String[] keys = params.keySet().toArray(new String[0]);
		Arrays.sort(keys);
		StringBuilder query = new StringBuilder();
		for (String key : keys) {
			if (!"signature".equals(key)) {
				String[] value = params.get(key);
				query.append(key);
				for (String string : value) {
					query.append(string);
				}
			}

		}
		LOGGER.debug("加密前：" + secretKey + query.toString());
		return MD5(secretKey + query.toString()).toUpperCase();
	}

	public static String MD5(String str) {

		try {
			MessageDigest m = MessageDigest.getInstance("MD5");
			m.reset();
			m.update(str.getBytes("UTF-8"));
			BigInteger bigInt = new BigInteger(1, m.digest());
			String hashtext = bigInt.toString(16);

			while (hashtext.length() < 32) {
				hashtext = "0" + hashtext;
			}
			return hashtext;

		} catch (Exception e) {
			throw new RuntimeException("MD5 init failed.", e);
		}
	}

	private static void println(HttpServletResponse response, CommonResult<Object> commonResult) throws IOException {
		response.setCharacterEncoding("utf-8");
		response.setContentType("text/html; charset=utf-8");
		PrintWriter pw = response.getWriter();
		pw.println(JSON.toJSON(commonResult));
		pw.flush();
		pw.close();
	}

	public static String toStr(String[] array) {
		StringBuffer sb = new StringBuffer();
		for (String string : array) {
			sb.append(string);
		}
		return sb.toString();
	}

	public static void main(String[] args) {
		System.out.println(MD5("ecd8d0c738cb6487cea6669f061048a8addressName中关村appId60c3fa21e92f4f52b30836bad42f8e0adoctorId18doctorWorkTime2016-11-28 09:00:00institutionId1signtime1480680153"));
	}

}
